package com.example.smartf.mqtt;

import com.example.smartf.config.MqttConfig;
import com.example.smartf.tool.UID;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class DownMqtt {
    //日志记录器
    private Logger logger = LoggerFactory.getLogger(getClass());

    private String HOST = UpMqtt.getInstance().getHost();
    private String clientid = UID.getUid();
    //板子返回信息时 发布的主体
    private String sub_topic;
    private MqttClient client;

    private Lock lock;
    private Condition condition;
    //需要传入的数据（username区分返回用户）
    private String username;

    public void setSub_topic(String topic){
        sub_topic = topic;
    }

    public void setLockAndCondition(Lock alock, Condition cond){
        lock = alock;
        condition = cond;
    }

    public void setUsername(String usern){
        username = usern;
    }

    //mqtt 配置选项
    private MqttConnectOptions getOptions(){
        MqttConnectOptions options = new MqttConnectOptions();

        // 设置自动清除session为false， false表示服务器保留客户端连接记录， true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(false);
        //设置超时时间 单位 秒
        options.setConnectionTimeout(50);
        //设置回话心跳时间， 单位 秒  每隔多长时间向客户端发送消息判断客户端是否在线，但是没有重连机制，只能判断客户端是否存活
        options.setKeepAliveInterval(12);
        //设置mqtt连入用户名
        options.setUserName(DownMqtt.Config.getUsername());
        //设置mqtt连入用户名密码
        options.setPassword(DownMqtt.Config.getPassword().toCharArray());
        return options;
    }

    //连接
    public void connect(){
        MqttConnectOptions options = getOptions();
        try{
            client = new MqttClient(HOST,clientid,new MemoryPersistence());
            client.setCallback(new DownCallback(lock,condition,username));
            client.connect(options);
            client.subscribe(sub_topic);
            logger.info("下行--连接 mqtt 代理 成功！");
        }catch (MqttException e){
            logger.warn("下行--连接 mqtt 代理失败：" + e.getMessage());
            connect();
        }
    }

    public void publish(String topic, String message){
        try{
            client.publish(topic, new MqttMessage(message.getBytes()));
        }catch (Exception e){
            logger.warn("下行--发布消息："+ e.getMessage());
        }
    }

    public void disconnect(){
        try{
            client.disconnect();
        }catch (MqttException e){
            logger.warn("下行--断开连接失败");
        }
        logger.info("下行--断开连接成功");
    }













    @Component
    private static class Config{
        @Autowired
        private MqttConfig mqttConfig;

        private static Config config;

        @PostConstruct
        public void init(){
            config = this;
            config.mqttConfig = this.mqttConfig;
        }

        static String getHost(){
            return config.mqttConfig.getHost();
        }

        static String getPassword(){
            return config.mqttConfig.getMqtt_password();
        }

        static String getUsername(){
            return config.mqttConfig.getMqtt_username();
        }
    }
}
